package swardToOffer.struct_4_tree;

import java.util.Arrays;

// 面试题33：二叉搜索树的后序遍历序列
// 题目：输入一个整数数组，判断该数组是不是某二叉搜索树的后序遍历的结果。
// 如果是则返回true，否则返回false。假设输入的数组的任意两个数字都互不相同。
// 思路：结合二叉搜索树和后续遍历的特点，可以得到该数组的最后一个元素index=n为根节点
// 遍历数组[0,n-1]，可以把该数组分为两部分，小于根节点的为左子树，大于根节点的为右子树
// 基于划分后的两个数组，分别做递归，如果当前的根节点没有左子树且右子树中存在比根节点更小的值，则返回false
public class SequenceOfBST {

    public boolean verifySequenceOfBST(int[] nums) {
        if (nums.length==0) return true;
        if (nums.length<0) return false;
//        return helper(nums, nums.length);
        return recur(nums, 0,nums.length-1);
    }

    private boolean helper(int[] nums, int length) {
        if (nums==null || length<0) return false;
        int root = nums[length-1];
        //在二叉搜索树中左子树节点的值小于根节点的值
        int i=0;
        for (; i < length-1; i++) {
            if (nums[i]>root) break;
        }
        int j=i;
        //在二叉搜索树中右子树节点的值大于根节点的值
        for(;j<length-1;j++){
            if (nums[j]<root) return false;
        }
        //判断左子树是否是二叉搜索树
        boolean le = true;
        if (i>0) le = helper(nums,i);
        //判断右子树是否是二叉搜索树
        boolean ri = true;
        if (i<length-1) ri=helper(Arrays.copyOfRange(nums,i,length),length-i-1);
        return le && ri;
    }

    boolean recur(int[] nums, int left, int right) {
        if(left >= right) return true;
        int p = left;
        //分割数组
        while(nums[p] < nums[right]) p++;
        int m = p;
        while(nums[p] > nums[right]) p++;
        // p==right说明右子树的所有值都比root值大
        return p == right && recur(nums, left, m - 1) && recur(nums, m, right - 1);
    }


    public static void main(String[] args) {
        int []  nums = {4, 8, 6, 12, 16, 14, 10};
        SequenceOfBST Main = new SequenceOfBST();
        System.out.println(Main.verifySequenceOfBST(nums));
    }

}
